home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / dev / c / vbcc.lha / vbcc / pasm / tables.c < prev    next >
C/C++ Source or Header  |  1998-02-17  |  10KB  |  338 lines

  1. /* $VER: pasm tables.c V0.8 (14.02.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v0.8 (14.02.98) phx
  16.  *      Alignment list for each section. This fixes the problems
  17.  *      with optimizations.
  18.  * v0.7 (01.01.98) phx
  19.  *      search_instr() is global.
  20.  * v0.5 (08.10.97) phx
  21.  *      .globl directive declares unknown symbols in pass 1 as
  22.  *      externally defined. If the symbol is defined later in the
  23.  *      source, it will be made global by add_symbol().
  24.  * v0.3 (05.04.97) phx
  25.  *      Minor changes.
  26.  * v0.2 (25.03.97) phx
  27.  *      Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  28.  *      or ELF output format may be selected. ELF is default for all
  29.  *      currently supported platforms. PPCasm supports nine different
  30.  *      relocation types (there are much more...).
  31.  *      Compiles and works also under NetBSD/amiga (68k).
  32.  *      Changed function declaration to 'new style' in all sources
  33.  *      (to avoid problems with '...' for example).
  34.  *      Externally defined symbols will automatically get global binding.
  35.  * v0.1 (11.03.97) phx
  36.  *      First test version with all PowerPC instructions and most
  37.  *      important directives. Only raw, absolute output.
  38.  * v0.0 (22.02.97) phx
  39.  *      File created.
  40.  */
  41.  
  42.  
  43. #define TABLES_C
  44. #include "ppcasm.h"
  45.  
  46.  
  47. void init_hashtables(struct GlobalVars *);
  48. void add_macro(struct GlobalVars *,struct Macro *);
  49. struct Symbol *add_symbol(struct GlobalVars *,char *,uint8,uint32);
  50. unsigned long elf_hash(unsigned char *);
  51. struct Symbol *search_symbol(struct GlobalVars *,char *);
  52. struct CPUInstr *search_instr(struct GlobalVars *,char *);
  53. struct Section *search_section(struct GlobalVars *,char *);
  54. void search_opcode(struct GlobalVars *,struct ParsedLine *,char *,char *);
  55.  
  56. static void *alloc_hashtable(size_t);
  57. static void add_instruction(struct GlobalVars *,struct CPUInstr *);
  58. static void add_directive(struct GlobalVars *,struct Directive *);
  59. static struct Directive *search_directive(struct GlobalVars *,char *);
  60. static struct Macro *search_macro(struct GlobalVars *,char *);
  61. static void execute_macro(struct GlobalVars *,struct ParsedLine *);
  62. static void execute_directive(struct GlobalVars *,struct ParsedLine *);
  63.  
  64.  
  65.  
  66. void init_hashtables(struct GlobalVars *gv)
  67. {
  68.   struct CPUInstr *ins = instructions;
  69.   struct Directive *dir = directives;
  70.  
  71.   gv->symbols = alloc_hashtable(SYMHTABSIZE);
  72.   gv->instr = alloc_hashtable(INSTRHTABSIZE);
  73.   gv->directives = alloc_hashtable(DIRHTABSIZE);
  74.   gv->macros = alloc_hashtable(MACROHTABSIZE);
  75.   while (ins->name)
  76.     add_instruction(gv,ins++);
  77.   while (dir->name)
  78.     add_directive(gv,dir++);
  79. }
  80.  
  81.  
  82. static void *alloc_hashtable(size_t entries)
  83. {
  84.   return (alloczero(entries * sizeof(void *)));
  85. }
  86.  
  87.  
  88. static void add_instruction(struct GlobalVars *gv,struct CPUInstr *ins)
  89. /* make new entry into instruction hash table */
  90. {
  91.   struct CPUInstr *chain;
  92.   unsigned long offs = elf_hash(ins->name)%INSTRHTABSIZE;
  93.  
  94.   if (!(ins->flags & F_EXTENDED) || !gv->noextmnemo) {
  95.     if (chain = gv->instr[offs])
  96.       ins->hash_chain = chain;
  97.     else
  98.       ins->hash_chain = NULL;
  99.     gv->instr[offs] = ins;
  100.   }
  101. }
  102.  
  103.  
  104. static void add_directive(struct GlobalVars *gv,struct Directive *dir)
  105. /* make new entry into directive hash table */
  106. {
  107.   struct Directive *chain;
  108.   unsigned long offs = elf_hash(dir->name)%DIRHTABSIZE;
  109.  
  110.   if (chain = gv->directives[offs])
  111.     dir->hash_chain = chain;
  112.   else
  113.     dir->hash_chain = NULL;
  114.   gv->directives[offs] = dir;
  115. }
  116.  
  117.  
  118. void add_macro(struct GlobalVars *gv,struct Macro *mac)
  119. /* make new entry into macro hash table */
  120. {
  121.   struct Macro *chain,*m;
  122.   unsigned long offs = elf_hash(mac->name)%MACROHTABSIZE;
  123.  
  124.   if (chain = m = gv->macros[offs]) {  /* hash code already used? */
  125.     do {
  126.       if (!strcmp(m->name,mac->name)) {
  127.         error(8,mac->name);  /* macro defined twice! */
  128.         break;
  129.       }
  130.     }
  131.     while (m = m->hash_chain);
  132.   }
  133.   gv->macros[offs] = mac;
  134.   mac->hash_chain = chain;
  135. }
  136.  
  137.  
  138. struct Symbol *add_symbol(struct GlobalVars *gv,char *name,uint8 type,
  139.                           uint32 value)
  140. /* define new symbol - absolute, relocatable or external */
  141. {
  142.   struct Symbol *sym,*chain;
  143.   unsigned long offs = elf_hash(name)%SYMHTABSIZE;
  144.  
  145.   if (chain = sym = gv->symbols[offs]) {  /* hash code already used? */
  146.     do {
  147.       if (!strcmp(name,sym->name)) {
  148.         if (sym->type == SYM_EXTERN) { /* declared ext. visible by .globl? */
  149.           if ((sym->type = type) == SYM_RELOC) {
  150.             sym->relsect = gv->csect;
  151.             sym->alignpoint = gv->csect->current_align;
  152.           }
  153.           sym->value = value;
  154.         }
  155.         else
  156.           error(7,name);  /* symbol defined twice! */
  157.         return (sym);
  158.       }
  159.     }
  160.     while (sym = sym->hash_chain);
  161.   }
  162.   gv->symbols[offs] = sym = alloczero(sizeof(struct Symbol));
  163.   sym->hash_chain = chain;
  164.   sym->name = allocstring(name);
  165.   sym->value = value;
  166.   if ((sym->type = type) == SYM_RELOC) {
  167.     sym->relsect = gv->csect;
  168.     sym->alignpoint = gv->csect->current_align;
  169.   }
  170.   else if (type == SYM_EXTERN)
  171.     sym->bind = SYMB_GLOBAL;
  172.   return (sym);
  173. }
  174.  
  175.  
  176. unsigned long elf_hash(unsigned char *name)
  177. /* calculate a hash code as used in ELF objects */
  178. {
  179.   unsigned long h=0,g;
  180.  
  181.   while (*name) {
  182.     h = (h << 4) + *name++;
  183.     if (g = h & 0xf0000000)
  184.       h ^= g >> 24;
  185.     h &= ~g;
  186.   }
  187.   return (h);
  188. }
  189.  
  190.  
  191. struct Symbol *search_symbol(struct GlobalVars *gv,char *name)
  192. /* find a symbol in the symbol hash table */
  193. {
  194.   struct Symbol *chain;
  195.   unsigned long offs = elf_hash(name)%SYMHTABSIZE;
  196.  
  197.   chain = gv->symbols[offs];
  198.   while (chain) {
  199.     if (!strcmp(chain->name,name))
  200.       return (chain);
  201.     chain = chain->hash_chain;
  202.   }
  203.   return (NULL);
  204. }
  205.  
  206.  
  207. struct CPUInstr *search_instr(struct GlobalVars *gv,char *name)
  208. /* find an instruction in the instruction hash table */
  209. {
  210.   struct CPUInstr *chain;
  211.   unsigned long offs = elf_hash(name)%INSTRHTABSIZE;
  212.  
  213.   chain = gv->instr[offs];
  214.   while (chain) {
  215.     if (!strcmp(chain->name,name))
  216.       return (chain);
  217.     chain = chain->hash_chain;
  218.   }
  219.   return (NULL);
  220. }
  221.  
  222.  
  223. static struct Directive *search_directive(struct GlobalVars *gv,char *name)
  224. /* find a directive in the directive hash table */
  225. {
  226.   struct Directive *chain;
  227.   unsigned long offs = elf_hash(name)%DIRHTABSIZE;
  228.  
  229.   chain = gv->directives[offs];
  230.   while (chain) {
  231.     if (!strcmp(chain->name,name))
  232.       return (chain);
  233.     chain = chain->hash_chain;
  234.   }
  235.   return (NULL);
  236. }
  237.  
  238.  
  239. static struct Macro *search_macro(struct GlobalVars *gv,char *name)
  240. /* find a macro in the macro hash table */
  241. {
  242.   struct Macro *chain;
  243.   unsigned long offs = elf_hash(name)%MACROHTABSIZE;
  244.  
  245.   chain = gv->macros[offs];
  246.   while (chain) {
  247.     if (!strcmp(chain->name,name))
  248.       return (chain);
  249.     chain = chain->hash_chain;
  250.   }
  251.   return (NULL);
  252. }
  253.  
  254.  
  255. struct Section *search_section(struct GlobalVars *gv,char *name)
  256. {
  257.   struct Section *nextsec,*sec=(struct Section *)gv->sectionlist.first;
  258.  
  259.   while (nextsec = (struct Section *)sec->n.next) {
  260.     if (!strcmp(name,sec->name))
  261.       return (sec);
  262.     sec = nextsec;
  263.   }
  264.   return (NULL);
  265. }
  266.  
  267.  
  268. void search_opcode(struct GlobalVars *gv,struct ParsedLine *pl,
  269.                    char *opname,char *operand)
  270. {
  271.   if (gv->alignflag)
  272.     pl->flags |= PLF_ALIGN;
  273.   gv->alignflag = FALSE;
  274.   if (pl->opcode = (void *)search_macro(gv,opname)) {
  275.     pl->type = OT_MACRO;
  276.     pl->operand = operand;
  277.     execute_macro(gv,pl);
  278.   }
  279.   else if (pl->opcode = (void *)search_instr(gv,opname)) {
  280.     pl->type = OT_INSTRUCTION;
  281.     pl->operand = allocstring(operand);
  282.     gv->csect->pc += 4;  /* every PPC instruction has a size of 4 bytes */
  283.   }
  284.   else if (pl->opcode = (void *)search_directive(gv,opname)) {
  285.     pl->type = OT_DIRECTIVE;
  286.     pl->operand = allocstring(operand);
  287.     execut